//导入工具包 require('node_modules里对应模块')
var gulp = require('gulp'),
    del = require('del'),
    fs = require('fs'),
    inject = require('gulp-inject'),
    htmlmin = require('gulp-htmlmin'),
    uglify = require('gulp-uglify'),
    rename = require("gulp-rename"),
    path = require('path'),
    merge = require('merge-stream'),
    cleanCSS = require('gulp-clean-css'),
    less = require('gulp-less'),
    randomstring = require('randomstring'),
    browserSync = require('browser-sync').create(),
    imagemin = require('gulp-imagemin'),
    extender = require('gulp-html-extend'),
    template = require('gulp-template'),
    $extend = require('extend'),
    reload = browserSync.reload;

var distDir = "dist/";
var defaultConfigTag = "include:default";
var resourceConfig = JSON.parse(fs.readFileSync('./config.json').toString("utf8"));
var templateConfig = JSON.parse(fs.readFileSync('./configTemplate.json').toString("utf8"));

// console.log(resourceConfig);
//需要copy的lib下的第三方js
var libResource = resourceConfig.default;
var templateDefault = templateConfig.default;
var globalKey = "$global";
var includeKey = "$include";

//获取目录下所有扩展名为{ext}文件
var getAllFiles = function(dir, ext) {
    var filesArray = [];
    var files = fs.readdirSync(dir);
    for (var i in files) {
        var fpath = path.join(dir, files[i]);
        var stat = fs.statSync(fpath);
        if (stat.isDirectory()) {
            var tempFiles = getAllFiles(fpath, ext);
            filesArray = filesArray.concat(tempFiles);
        } else if (stat.isFile()) {
            var index = fpath.indexOf('.', -1);
            var fext = fpath.substr(index + 1);
            if (ext === fext) {
                filesArray.push(fpath);
            }
        }
    }
    return filesArray;
};

var combineStreamConfigInject = function(file, injectLibResource, fileWithoutExt, baseDir, baseStream) {
    var stream = baseStream ? baseStream : gulp.src(file);
    var replaceStr = baseDir;
    for (var key in injectLibResource) {
        var injectObj;
        var resources;
        var libRes = injectLibResource[key];
        for (var i = 0; i < libRes.length; i++) {
            var firstChar = libRes[i].substr(0, 1);
            var startIndex = firstChar === '!' ? 1 : 0;
            var firstDir = libRes[i].substr(startIndex, replaceStr.length);
            if (firstDir !== replaceStr) {
                libRes[i] = libRes[i].replace('lib', path.join(replaceStr, 'lib'));
            }
        }
        if (key === globalKey) {
            injectObj = {
                relative: true,
                removeTags: baseDir !== 'src'
            }
        } else {
            injectObj = {
                relative: true,
                starttag: '<!-- inject:' + key + ':{{ext}} -->',
                removeTags: baseDir !== 'src'
            }
        }
        try {
            resources = gulp.src(libRes, {
                read: false
            });
        } catch (e) {
            console.log(libRes);
            throw new Error("[Error]---------->请检查config.json中配置项" + fileWithoutExt + "是否正确");
        }
        if (resources && injectObj) {
            stream = stream.pipe(inject(resources, injectObj));
        }
    }
    return stream;
};

var concatWithoutSame = function(arr1, arr2) {
    for (var i = 0; i < arr1.length; i++) {
        for (var j = 0; j < arr2.length; j++) {
            if (arr1[i] === arr2[j]) {
                arr1.splice(i, 1); //利用splice函数删除元素，从第i个位置，截取长度为1的元素
            }
        }
    }
    //alert(arr1.length)
    for (var i = 0; i < arr2.length; i++) {
        arr1.push(arr2[i]);
    }
    return arr1;
}

var combineConfig = function(config1, config2) {
    for (var key in config2) {
        if (config1[key]) {
            var config1List = config1[key];
            var config2List = config2[key];
            config1[key] = concatWithoutSame(config1List, config2List);
        } else {
            config1[key] = config2[key];
        }
    }
};

var getLibConfigResourceByItem = function(baseDir, configItem, injectLibResource) {
    //如果在配置文件中
    var libConfigResource = {};
    for (var key in configItem) {
        var configList = configItem[key];
        if (key === includeKey) {
            for (var i in configList) {
                var val = configList[i];
                if (val === defaultConfigTag) {
                    combineConfig(libConfigResource, injectLibResource);
                } else {
                    var includeConfig = resourceConfig[val.substr(8)];
                    if (includeConfig) combineConfig(libConfigResource, getLibConfigResourceByItem(baseDir, includeConfig, injectLibResource));
                }
            }
            break;
        }
    }
    combineConfig(libConfigResource, configItem);
    delete configItem[includeConfig];
    return libConfigResource;
}


var injectOneFile = function(baseDir, injectLibResource, destType, file, baseStream) {
        var index1 = file.indexOf('.');
        var index2 = file.lastIndexOf(path.sep);
        var index3 = file.indexOf(path.sep);
        var fileWithoutExt = file.substr(index2 + 1, index1 - index2 - 1);
        var desDir = file.substr(0, index2);
        var businessArray = [];

        var jsResource = path.join(baseDir, '**', fileWithoutExt + destType + '.js');
        var cssResource = path.join(baseDir, '**', fileWithoutExt + destType + '.css');
        businessArray = [jsResource, cssResource];
        var businessJs = gulp.src(businessArray, {
            read: false
        }).pipe(rename(function(p) {
            p.extname = p.extname + '?v=' + randomstring.generate(6);
        }));

        //如果在配置文件中
        var stream;
        if (resourceConfig[fileWithoutExt]) {
            var configItem = resourceConfig[fileWithoutExt];
            var t = getLibConfigResourceByItem(baseDir, configItem, injectLibResource);
            stream = combineStreamConfigInject(file, t, fileWithoutExt, baseDir, baseStream);
        } else {
            stream = combineStreamConfigInject(file, injectLibResource, fileWithoutExt, baseDir, baseStream);
        }
        var tplConfig = templateConfig[fileWithoutExt];
        tplConfig = tplConfig ? tplConfig : {};
        tplConfig = $extend(templateDefault, tplConfig);
        stream.pipe(inject(businessJs, {
                relative: true,
                starttag: '<!-- inject:business:{{ext}} -->',
                removeTags: true
            }))
            .pipe(template(tplConfig))
            .pipe(gulp.dest(desDir));
        return stream;
    }
    //baseDir: 'src' 或 'dir'
    //injectLibResource: libResource 或 dist下libResource
    //destType: '' 或 '.min'
var getInjectHtmlResourceStreams = function(baseDir, injectLibResource, destType) {
    var streams = [];
    var files = getAllFiles(baseDir, 'html');
    for (var i in files) {
        var stream = injectOneFile(baseDir, injectLibResource, destType, files[i]);
        streams.push(stream);
    }
    return streams;
};

//清理dist，默认删除所有文件
gulp.task('clean:dist', function() {
    del.sync([distDir + '**']);
    fs.mkdirSync('dist');
});

//清理tmp，默认删除所有文件
gulp.task('clean:tmp', function() {
    del.sync(['tmp/**']);
    fs.mkdirSync('tmp');
});

//把src下images复制到dist下
gulp.task('build:images', function() {
    return gulp.src('src/images/**/*')
        .pipe(imagemin({
            progressive: true
        }))
        .pipe(gulp.dest(distDir + 'images'));
});

gulp.task('build:less', ['build:css'], function() {
    return gulp.src('src/**/*.less')
        .pipe(less())
        .pipe(cleanCSS())
        .pipe(rename(function(path) {
            path.basename += '.min';
        }))
        .pipe(gulp.dest(distDir));
});

//把src下css复制到dist下，并压缩重命名
gulp.task('build:css', function() {
    return gulp.src(['src/**/*.css', '!src/lib/**/*.css'])
        .pipe(cleanCSS())
        .pipe(rename(function(path) {
            path.basename += '.min';
        }))
        .pipe(gulp.dest(distDir));
});

//把src下js复制到dist下，并压缩重命名
gulp.task('build:js', function() {
    return gulp.src(['src/**/*.js', '!src/lib/**/*.js'])
        .pipe(uglify())
        .pipe(rename(function(path) {
            path.basename += ".min";
        }))
        .pipe(gulp.dest(distDir));
});

gulp.task('build:lib-copy', function() {
    var cssStream = gulp.src('src/lib/**/*.css')
        .pipe(cleanCSS())
        .pipe(gulp.dest('lib/'));
    var jsStream = gulp.src('src/lib/**/*.js')
        .pipe(uglify())
        .pipe(gulp.dest('lib/'));
    return merge([cssStream, jsStream]);
});

//把lib复制到dist下
gulp.task('build:lib', ['build:lib-copy'], function() {
    var libListResource = [];
    for (var key in libResource) {
        libListResource = libListResource.concat(libResource[key]);
    }
    return gulp.src(libListResource)
        .pipe(gulp.dest(distDir + 'lib/'));
});

//把src下html复制到dist下
gulp.task('build:html', ['build:lib'], function() {
    return gulp.src('src/**/*.html')
        .pipe(extender())
        .pipe(gulp.dest(distDir));
});

//注入相应的js和css
gulp.task('build:injecthtml', ['build:html', 'build:js', 'build:less'], function() {
    var distLibResource = JSON.parse(JSON.stringify(libResource));
    var streams = getInjectHtmlResourceStreams('dist', distLibResource, '.min');
    return merge(streams);
});

//在inject完resource后，最后压缩html
gulp.task('build:html-final', ['build:injecthtml'], function() {
    return gulp.src(distDir + '**/*.html')
        .pipe(htmlmin({
            collapseWhitespace: true
        }))
        .pipe(gulp.dest(distDir));
});
//*******************src build script begin*******************
gulp.task('build:src-images', function() {
    return gulp.src('src/images/**/*.*')
        .pipe(gulp.dest('tmp/images'));
});

gulp.task('build:src-less', function() {
    return gulp.src('src/**/*.less')
        .pipe(less())
        .pipe(gulp.dest('tmp/'));
});

gulp.task('build:src-lib', ['build:lib-copy'], function() {
    var libListResource = [];
    for (var key in libResource) {
        libListResource = libListResource.concat(libResource[key]);
    }
    return gulp.src(libListResource)
        .pipe(gulp.dest('tmp/lib'));
});

gulp.task('build:src-html', function() {
    return gulp.src('src/**/*.html')
        .pipe(extender())
        .pipe(gulp.dest('tmp/'));
});

gulp.task('build:src-css', function() {
    return gulp.src('src/**/*.css')
        .pipe(gulp.dest('tmp/'));
});

gulp.task('build:src-js', function() {
    return gulp.src('src/**/*.js')
        .pipe(gulp.dest('tmp/'));
});

//注入相应的js和css
gulp.task('build:src', ['clean:tmp',
    'build:src-less',
    'build:src-images',
    'build:src-lib',
    'build:src-html',
    'build:src-css',
    'build:src-js'
], function() {
    var tmpLibResource = JSON.parse(JSON.stringify(libResource));
    var streams = getInjectHtmlResourceStreams('tmp', tmpLibResource, '');
    return merge(streams);
});
//*******************src build script end*******************

var changeFile;
gulp.task('build:tmp-html', ['build:src-html'], function() {
    templateConfig = JSON.parse(fs.readFileSync('./configTemplate.json').toString("utf8"));
    templateDefault = templateConfig.default;
    var tmpLibResource = JSON.parse(JSON.stringify(libResource));
    if (changeFile) {
        var index = changeFile.lastIndexOf(path.sep);
        var index2 = changeFile.lastIndexOf('src' + path.sep);
        var filename = changeFile.substr(index + 1);
        var s1 = gulp.src(changeFile.substr(index2))
            .pipe(extender());
        var tmpPath = path.join('tmp', changeFile.substr(index2 + 4));
        return injectOneFile('tmp', tmpLibResource, '', tmpPath, s1);
    } else {
        var streams = getInjectHtmlResourceStreams('tmp', tmpLibResource, '');
        return merge(streams);
    }
});

gulp.task('build:reload', ['build:tmp-html'], function() {
    changeFile = undefined;
    reload();
});

// 静态服务器
gulp.task('browser-sync', function() {
    browserSync.init({
        server: {
            baseDir: "./"
        }
    });
    // js", "src/**/*.html", "src/**/*.css
    gulp.watch("src/**/*.js", ['build:src-js']).on("change", reload);
    gulp.watch("src/**/*.css", ['build:src-css']).on("change", reload);
    gulp.watch("src/**/*.less", ['build:src-less']).on("change", reload);
    gulp.watch(["src/**/*.html", "src/**/*.tpl", "configTemplate.json"], ['build:reload']);
    // gulp.watch(["src/**/*.html", "src/**/*.tpl", "configTemplate.json"], function(event) {
    //     var timer = setInterval(function(){
    //         if (changeFile) {
    //             return;
    //         }
    //         changeFile = event.path;
    //         gulp.run("build:reload");
    //         clearInterval(timer);
    //     }, 200);
    // });
});
gulp.task('default', ['clean:dist', 'build:images', 'build:html', 'build:html-final']);
